package avicit.bdp.dms.prm.rest;

import avicit.bdp.dms.dss.enums.ApiCallStatus;
import avicit.bdp.dms.oauth2.OAuthTokenHandleDispatcher;
import avicit.bdp.dms.oauth2.WebUtils;
import avicit.platform6.api.system.SysUserClient;
import avicit.platform6.commons.utils.AesEncryptUtil;
import avicit.platform6.core.app.JWTUtils;
import avicit.platform6.core.redis.RedisUtil;
import avicit.platform6.core.rest.msg.ResponseMsg;
import avicit.platform6.core.spring.SpringFactory;
import com.auth0.jwt.interfaces.DecodedJWT;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 公共对外服务
 *
 * @author xugb
 */
@RestController
@Api(tags = "公共对外服务")
@RequestMapping("/api/bdp/dms/pub")
public class PubServiceRest {

    private static final Logger logger = LoggerFactory.getLogger(PubServiceRest.class);
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SysUserClient userClient;

    /**
     * token校验服务
     */
    @ApiOperation(value = "用户Token校验")
    @ApiImplicitParam(value = "token", name = "token", dataType = "String")
    @RequestMapping(path = "/validateToken",method={RequestMethod.POST,RequestMethod.GET})
    public ResponseMsg<Map<String, Object>> validateToken(@RequestParam String token) {
        ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
        if (StringUtils.isNotEmpty(token)) {
            try {
                JWTUtils.verifyToken(token);
                DecodedJWT jwt = JWTUtils.decodeToken(token);
                String appId = jwt.getClaim("APP_ID").asString();
                String accesskeyId = JWTUtils.getAccessKeyId(token);
                this.validateAccessKeyId(accesskeyId, appId, false);
                String userName = jwt.getClaim("USER_NAME").asString();
                String userCode = jwt.getClaim("USER_CODE").asString();
                String userId = jwt.getAudience().get(0);
                String orgId = jwt.getClaim("ORG_IDENTITY").asString();
                String deptId = jwt.getClaim("USER_DEPT_ID").asString();
                String languageCode = jwt.getClaim("LANGUAGE_CODE").asString();
                String secretLevel = jwt.getClaim("SECRET_LEVEL").asString();
                Map<String, Object> userMap = new HashMap<>();
                userMap.put("userId", userId);
                userMap.put("userName", userName);
                userMap.put("userCode", userCode);
                userMap.put("orgId", orgId);
                userMap.put("deptId", deptId);
                userMap.put("languageCode", languageCode);
                userMap.put("secretLevel", secretLevel);
                responseMsg.setRetCode(String.valueOf(ApiCallStatus.SUCCESS.getCode()));
                responseMsg.setResponseBody(userMap);
            } catch (AuthenticationException e) {
                responseMsg.setRetCode(String.valueOf(ApiCallStatus.TOKEN_INVALID.getCode()));
                responseMsg.setErrorDesc("token校验失败：" + e.getMessage());
            } catch (Exception e) {
                responseMsg.setRetCode(String.valueOf(ApiCallStatus.TOKEN_INVALID.getCode()));
                responseMsg.setErrorDesc("token校验失败：" + e.getMessage());
            }

        } else {
            responseMsg.setRetCode(String.valueOf(ApiCallStatus.TOKEN_INVALID.getCode()));
            responseMsg.setErrorDesc("未传token信息");
        }

        return responseMsg;
    }

    /**
     * token校验服务
     */
    @ApiOperation(value = "用户Token校验")
    @ApiImplicitParam(value = "token", name = "token", dataType = "String")
    @RequestMapping(path = "/validateUserToken",method={RequestMethod.POST,RequestMethod.GET})
    public Map<String, Object> validateUserToken(@RequestParam String token) {
       Map<String, Object> result = new HashMap<>();
        if (StringUtils.isNotEmpty(token)) {
            try {
                JWTUtils.verifyToken(token);
                DecodedJWT jwt = JWTUtils.decodeToken(token);
                String appId = jwt.getClaim("APP_ID").asString();
                String accesskeyId = JWTUtils.getAccessKeyId(token);
                this.validateAccessKeyId(accesskeyId, appId, false);
                String userName = jwt.getClaim("USER_NAME").asString();
                String userCode = jwt.getClaim("USER_CODE").asString();

                result.put("status",200);
                result.put("message","校验成功");
                result.put("data",userCode);

            } catch (Exception e) {
                result.put("status",500);
                result.put("message","Token校验失败");
                result.put("data","");
            }

        } else {
            result.put("status",500);
            result.put("message","未传Token信息");
            result.put("data","");
        }

        return result;
    }

    private void validateAccessKeyId(String accesskeyId, String appId, boolean notUpdateSession) {
        if (StringUtils.isNotBlank(accesskeyId)) {
            String sid = null;

            try {
                sid = AesEncryptUtil.aesDecrypt(URLDecoder.decode(accesskeyId, "utf-8"), "dufy20170329java");
            } catch (Exception var8) {
                throw new AuthenticationException("sid无效");
            }

            String sessionKey = "avicit:sys:session:" + sid + appId;
            if (this.redisUtil == null) {
                this.redisUtil = (RedisUtil) SpringFactory.getBean(RedisUtil.class);
            }

            boolean hasKey = this.redisUtil.hasKey(sessionKey);
            if (!hasKey) {
                throw new AuthenticationException("token失效");
            }

            if (notUpdateSession) {
                return;
            }

            if (this.userClient == null) {
                this.userClient = (SysUserClient) SpringFactory.getBean(SysUserClient.class);
            }

            int userSessionTimeout = this.userClient.getUserSessionTimeout();
            if (userSessionTimeout > 0) {
                this.redisUtil.expire(sessionKey, (long) userSessionTimeout);
            }
        }

    }

    @PostMapping({"/getToken"})
    public void authorize(HttpServletRequest request, HttpServletResponse response) throws OAuthSystemException {
        try {
            OAuthTokenRequest tokenRequest = new OAuthTokenRequest(request);
            OAuthTokenHandleDispatcher tokenHandleDispatcher = new OAuthTokenHandleDispatcher(tokenRequest, response);
            tokenHandleDispatcher.dispatch();
        } catch (OAuthProblemException var5) {
            logger.error(var5.getMessage(), var5);
            OAuthResponse tokenResponse = OAuthResponse.errorResponse(400).setError(var5.getError()).setErrorDescription(var5.getDescription()).buildJSONMessage();
            WebUtils.writeOAuthJsonResponse(response, tokenResponse);
        }

    }

}
